home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 06 - 1990 / 06.02 Feb 90 / Mouse Source / TrackClick.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-07-22  |  5.9 KB  |  206 lines  |  [TEXT/KAHL]

  1. /*                                            TrackClick.c                                        */
  2. /*
  3.  * Copyright © 1989 Martin Minow. All rights reserved.
  4.  *
  5.  * You may incorporate portions of this program in your
  6.  * applications without restriction as long as this
  7.  * copyright notice remains intact and the applications
  8.  * are not sold for profit and the source is not
  9.  * redistributed for profit.
  10.  *
  11.  * TrackClick(mouse, extend, track_handle)
  12.  * mouse                The mouse location in local coordinates.
  13.  * extend                TRUE to extend the selection.
  14.  * track_handle    Everything we need to know about the data.
  15.  *
  16.  * Process a mouse button click in the document window.
  17.  *
  18.  * If clikProc is non-NIL, the function will be called
  19.  * repeatedly as follows:
  20.  *     (*clikProc)(mouse, TrackPtr)
  21.  * Your function should be declared
  22.  *    pascal Boolean
  23.  *    myClikLoop(Point mouse, TrackPtr trackptr)
  24.  * where
  25.  *    mouse            mouse location in window-local coordinates.
  26.  *    trackptr    pointer to a locked TrackRecord.
  27.  * If the myClikLoop returns FALSE, TrackClick will assume
  28.  * that the mouse button has been released.
  29.  * If clikProc is NIL, TrackClick will autoscroll if the
  30.  * mouse moves outside of the viewRect.
  31.  */
  32. #include    "TrackEdit.h"
  33. #define TR    (*tr)
  34. #define NIL            0
  35.  
  36. /*
  37.  * save_select is used for double-clicks to ensure that
  38.  * the TrackRecord has the current selection.
  39.  */
  40. #define save_select(tr, a, c)    do {        \
  41.             if (a.start <= c.end) {                    \
  42.                 (tr)->selStart = a.start;            \
  43.                 (tr)->selEnd = c.end;                    \
  44.             }                                                                \
  45.             else {                                                    \
  46.                 (tr)->selStart = c.start;            \
  47.                 (tr)->selEnd = a.end;                    \
  48.             }                                                                \
  49.         } while (0)
  50.  
  51.  
  52. void
  53. TrackClick(mouse, shift_click, track_handle)
  54. Point                    mouse;
  55. Boolean                shift_click;
  56. TrackHandle        track_handle;
  57. {
  58.         register TrackPtr            tr;
  59.         _Track_state                    state;
  60.         register DOT                    dot;
  61.         register Boolean            is_word;
  62.         register DOT                    temp;
  63.         register DOT                    last_word;
  64.         auto _Track_Loc                anchor;
  65.         auto _Track_Loc                current;
  66.         DOT                                        last_end, new_end;
  67.         Boolean                                at_anchor;
  68.         
  69.         tr = _Track_lock(track_handle, &state);
  70.         dot = _Track_mouse_to_dot(tr, mouse);
  71.         is_word = FALSE;
  72.         _Track_caret(tr, _Track_caret_off);
  73.         if (shift_click && TR.selStart != TR.selEnd) {
  74.             /*
  75.              * Extend the selection.  If the mouse is outside
  76.              * the current selection, extend from the mouse
  77.              * to the nearest end (the selection always gets
  78.              * bigger).  Otherwise, truncate from the start
  79.              * (left).  Note: some applications just continue
  80.              * from the current invocation, but I don't think
  81.              * this looks good.  Shift-click doesn't do
  82.              * word-by-word (double-click) extension.
  83.              */
  84.             if (dot > TR.selStart)
  85.                 _Track_hilite(tr, dot, TR.selEnd);
  86.             else {
  87.                 _Track_hilite(tr, dot, TR.selStart);
  88.                 TR.selStart = TR.selEnd;
  89.             }
  90.             TR.selEnd = dot;
  91.         }
  92.         else {
  93.             /*
  94.              * Not shift-click with a selection.  Dump any
  95.              * previous selection. (_Track_Hilite does nothing
  96.              * if it's called with no selection.)
  97.              */
  98.             _Track_hilite(tr, TR.selStart, TR.selEnd);
  99.             TR.selStart = TR.selEnd = dot;
  100.             /*
  101.              * Check for a double-click.  If so, extend the
  102.              * selection to encompass the entire word.
  103.              */
  104.             if ((TickCount() - TR.clickTime) <= GetDblTime()
  105.              && dot == TR.clickLoc) {
  106.                  is_word = TRUE;
  107.                  _Track_word(tr, mouse, &anchor);
  108.                  _Track_hilite(tr, anchor.start, anchor.end);
  109.                  current = anchor;
  110.                 last_word = anchor.start;
  111.                 at_anchor = TRUE;
  112.             }
  113.         }
  114.         /*
  115.          * Track the mouse, extending the visual selection
  116.          * whenever it moves off-character.
  117.          */
  118.         while (WaitMouseUp()) {
  119.             temp = dot;
  120.             do {
  121.                 GetMouse(&mouse);
  122.                 if (is_word)
  123.                     save_select(tr, anchor, current);
  124.                 if (TR.clikLoop != NIL
  125.                  && !CallPascalB(mouse, tr, TR.clikLoop)) {
  126.                     goto done;
  127.                 }
  128.                 else {
  129.                     _Track_autoscroll(tr, &mouse);
  130.                 }
  131.                 dot = _Track_mouse_to_dot(tr, mouse);
  132.             } while (dot == temp && StillDown());
  133.             if (is_word) {
  134.                 /*
  135.                  * Word-by-word selection: the mouse moved.
  136.                  * Check to see if the mouse is in the same word.
  137.                  * If so, do nothing.  Else, extend the selection
  138.                  * to the new word.
  139.                  */
  140.                  _Track_word(tr, mouse, ¤t);
  141.                 if (current.start != last_word) {
  142.                     /*
  143.                      * The mouse moved off the current word. The
  144.                      * word is always identified by the location of
  145.                      * its left end.  Invert the selection.  If the
  146.                      * mouse is before (left of) the current point,
  147.                      * invert from the start of the word, else from
  148.                      * the end of the word.  Note that the word
  149.                      * that the user clicked on is not un-hilited.
  150.                      */
  151.                     last_word = current.start;
  152.                     if (current.start < anchor.start) {
  153.                         new_end = current.start;
  154.                         if (at_anchor)
  155.                             last_end = anchor.start;
  156.                         else if (last_end > anchor.start) {
  157.                             _Track_hilite(tr, last_end, anchor.end);
  158.                             last_end = anchor.start;
  159.                         }
  160.                     }
  161.                     else /* if (current.start >= anchor.start) */ {
  162.                         new_end = current.end;
  163.                         if (at_anchor)
  164.                             last_end = anchor.end;
  165.                         else if (last_end < anchor.start) {
  166.                             _Track_hilite(tr, last_end, anchor.start);
  167.                             last_end = anchor.end;
  168.                         }
  169.                     }
  170.                     _Track_hilite(tr, last_end, new_end);
  171.                     last_end = new_end;
  172.                     at_anchor = (current.start == anchor.start);
  173.                 }
  174.             }
  175.             else {
  176.                 /*
  177.                  * Normal (not word) selection. Just invert from
  178.                  * the info->select.end point to the mouse postion.
  179.                  */
  180.                 _Track_hilite(tr, dot, TR.selEnd);
  181.                 TR.selEnd = dot;
  182.             }
  183.         }
  184.         /*
  185.          * Done! remember the mouse location for a subsequent
  186.          * double-click, and normalize the selection (so that
  187.          * info->select.start < info->select.end).  If this
  188.          * was a zero-width selection, the user was setting
  189.          * the insertion point, which should be marked.
  190.          */
  191. done:
  192.         TR.clickTime = TickCount();
  193.         TR.clickLoc = dot;
  194.         if (is_word)
  195.             save_select(tr, anchor, current);
  196.         else if (TR.selStart > TR.selEnd) {
  197.             dot = TR.selStart;
  198.             TR.selStart = TR.selEnd;
  199.             TR.selEnd = dot;
  200.         }
  201.         TR.selRow = _Track_pixel_row(tr, mouse.v);
  202.         _Track_caret(tr, _Track_caret_on);
  203.         _Track_unlock(&state);
  204. }
  205.  
  206.